﻿using System;
using System.Collections;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.ComponentModel.Design.Serialization;
using System.Drawing;
using System.IO;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Windows.Forms.Design.Behavior;
using System.Xml;
using CXMLStudioIDE.Common;
using CXMLStudioIDE.DesignerHost;
using CXMLStudioIDE.WinFormsUI.CXMLStudioControls;
using CXMLStudioIDE.WinFormsUI.Docking;
using System.Threading;
using System.Diagnostics;
using CXMLStudioIDE.Forms;
using CXMLStudioIDE.BusinessLayer;
using CXMLStudioIDE.Common.Entities;
using CXMLStudioIDE.DataAccessLayer;
using System.Collections.Generic;
using CXMLStudioIDE.Common.EntityProperties;
using System.Reflection;
using System.Runtime.Serialization;
using System.Data;
using CXMLStudioIDE.Views;
using CXMLStudioIDE.Presenters;

namespace CXMLStudioIDE
{
    public partial class FormDesigner : DockContent, IFormDesignerView
    {
        #region Declarations

        private ServiceContainer serviceContainer = null;
        private IMenuCommandService menuService = null;
        private Form m_form;
        private IDesignerHost host;
        private IRootDesigner rootDesigner;
        private Control view;
        public static bool isBuildingForm = false;
        public enum SameSizeEnum { Width, Height, Both };
        public enum AlignEnum { Top, Bottom, Right, Left };
        public static BehaviorService m_behaviorservice = null;
        public Form m_parent;
        private string m_filename;
        public DesignSurface m_designsurface;
        private PropertiesDAL m_propsdal = null;
        private PropertiesBL m_propsbl = null;
        private BusinessEntity _RootBusinessEntity = null;
        private bool isFormCompleted = false;
        private FormDesignerPresenter m_presenter;
        private Type _EntityType = null;

        #endregion
        #region Worker Delegate declaration
        delegate void AddControlsDelegate(CXMLTreeNode node);
        delegate void InitProgressBarDelegate(int count);
        delegate void ResumeLayoutDelegate(int nodecount);
        delegate void SuspendLayoutDelegate();
        delegate void PerformStepDelegate();
        #endregion

        #region Events
        public delegate void OnFormCompletedEventHandler(object sender);
        public delegate void OnEntityDroppedEventHandler(object sender);
        public event OnFormCompletedEventHandler OnFormCompleted;
        public event OnEntityDroppedEventHandler OnEntityDroppedInFormDesigner;
        #endregion

        #region Constructors

        //If no filename sent then build an empty Form Designer
        //If filename sent then deserialize XML into a form.
        public FormDesigner(Form parent, string _filename)
        {
            m_parent = parent;
            m_filename = _filename;
            InitializeComponent();
            InitForm(_filename);
            m_propsdal = new PropertiesDAL();
            m_propsbl = new PropertiesBL();
            m_presenter = new FormDesignerPresenter(this);
        }

        #endregion

        #region Properties
        public BusinessEntity RootBusinessEntity
        {
            get
            {
                return _RootBusinessEntity;
            }
            set
            {
                _RootBusinessEntity = value;
            }
        }
        public Type EntityType
        {
            get { return _EntityType; }
            set { _EntityType = value; }
        }
        #endregion

        private void InitForm(string filename)
        {
            //SERVICES
            serviceContainer = new ServiceContainer();
            serviceContainer.AddService(typeof(INameCreationService), new NameCreationService());
            if (filename == null)
            {
                host = new CXMLStudioIDE.DesignerHost.DesignerHost(serviceContainer);
                // Start the designer host off with a Form to design
                m_form = (Form)host.CreateComponent(typeof(Form));
                //form.TopLevel = false;
                m_form.Text = "Form1";
                m_form.AllowDrop = true;
                //m_form.AutoSize = true;
                m_form.AutoScroll = true;
                m_form.Location = new Point(0, 0);
                //m_form.Size = new Size(500, 500);
                //m_form.MaximumSize = new System.Drawing.Size(0, 0);
                m_form.Size = System.Windows.Forms.Screen.GetBounds(this).Size;
                m_form.Height = Convert.ToInt32(System.Windows.Forms.Screen.GetBounds(this).Height * 0.65);
                m_form.Width = Convert.ToInt32(System.Windows.Forms.Screen.GetBounds(this).Width * 0.65);
                pnl_Progress.Location = new Point(Convert.ToInt32((m_form.Width / 2) * 0.7), m_form.Height / 2);
                // Add menu command service
                //menuService = new CXMLStudioIDE.DesignerHost.MenuCommandService(host);
                //serviceContainer.AddService(typeof(IMenuCommandService), menuService);
            }
            else
            {
                BasicHostLoader bhl = new BasicHostLoader(filename);
                host = new CXMLStudioIDE.DesignerHost.DesignerHost(serviceContainer);
                ((CXMLStudioIDE.DesignerHost.DesignerHost)host).BeginLoad(bhl);
                m_form = host.RootComponent as Form;
                this.Text = "Form Designer - " + m_form.Text;
                TextBox txt = m_form.Controls["txt_95"] as TextBox;
                if (txt != null)
                {
                    IDesigner designer = host.GetDesigner(txt);
                    DesignerVerbCollection dvc = designer.Verbs;
                }
            }

            m_form.DragEnter += new DragEventHandler(pnlDragHere_DragEnter);
            pnlViewHost.MaximumSize = new System.Drawing.Size(0, 0);

            //// Add menu command service
            //menuService = new CXMLStudioIDE.DesignerHost.MenuCommandService(host);
            //serviceContainer.AddService(typeof(IMenuCommandService), menuService);
            menuService = (IMenuCommandService)serviceContainer.GetService(typeof(IMenuCommandService));

            // Get the root designer for the form and add its design view to this form
            rootDesigner = (IRootDesigner)host.GetDesigner(m_form);
            view = (Control)rootDesigner.GetView(ViewTechnology.Default);
            view.Dock = DockStyle.Fill;
            view.MaximumSize = new System.Drawing.Size(0, 0);
            //pnlViewHost.Size = m_form.Size;
            pnlViewHost.Size = System.Windows.Forms.Screen.GetBounds(this).Size;
            pnlViewHost.Controls.Add(view);
            //pnl_BusEntityInfo.Dock = DockStyle.Top;
            //pnlViewHost.Dock = DockStyle.Bottom;

            //CollapsiblePanel panel test
            //For Design mode on
            //CollapsiblePanel cp = (CollapsiblePanel)host.CreateComponent(typeof(CollapsiblePanel));
            //For Design mode off
            //CollapsiblePanel cp = new CollapsiblePanel();

            //cp.BackColor = System.Drawing.Color.Transparent;
            //cp.HeaderFont = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold);
            //cp.HeaderImage = null;
            //cp.HeaderText = "CollapsiblePanel";
            //cp.HeaderTextColor = System.Drawing.Color.Black;
            //cp.Location = new System.Drawing.Point(12, 26);
            //cp.Name = "collapsiblePanel1";
            //cp.Size = new System.Drawing.Size(250, 150);
            //cp.TabIndex = 0;

            // Subscribe to the selectionchanged event and activate the designer
            ISelectionService s = (ISelectionService)serviceContainer.GetService(typeof(ISelectionService));
            s.SelectionChanged += new EventHandler(OnSelectionChanged);
            host.Activate();

            // ADD GLOBAL CONTEXTUAL MENU ITEMS HERE
            //Add the Verbs for contextual menus UN-COMMENT THE FOLLOWING
            //DesignerVerb m_Verb = new DesignerVerb("Properties", new EventHandler(OnPropertiesSelected));
            //menuService.AddVerb(m_Verb);
            //m_Verb = new DesignerVerb("Second Designer Verb", new EventHandler(OnSecondItemSelected));
            //menuService.AddVerb(m_Verb);         


            //Subscribe to properties changes
            //MainForm.m_propertyWindow.PropertyValueChanged += new PropertyWindowForm.OnPropertyValueChanged(FormDesigner_PropertyValueChanged);
            //MainForm.m_propertyWindow.PropertyChanged += new PropertyWindowForm.OnPropertyChanged(FormDesigner_PropertyChanged);
            //NodeToControls(((MainForm)m_parent).m_tvWindow.cxmlTreeView1.Nodes[0] as CXMLTreeNode);
            ((CXMLStudioIDE.DesignerHost.DesignerHost)host).ComponentChanged += new ComponentChangedEventHandler(FormDesigner_ComponentChanged);
        }

        void FormDesigner_PropertyValueChanged(object obj, PropertyValueChangedEventArgs e)
        {
        }

        private void mnuDelete_Click(object sender, System.EventArgs e)
        {
            menuService.GlobalInvoke(StandardCommands.Delete);
        }

        private void Panel_Paint(object sender, PaintEventArgs e)
        {

        }

        private void MakeSameSize(SameSizeEnum ss)
        {
            ISelectionService s = (ISelectionService)serviceContainer.GetService(typeof(ISelectionService));
            //ArrayList controls = s.GetSelectedComponents() as ArrayList;
            object[] selection = new object[s.SelectionCount];
            s.GetSelectedComponents().CopyTo(selection, 0);
            int i = 0;
            int Width = 0;
            int Height = 0;

            foreach (Control c in selection)
            {
                if (i == 0)
                {
                    Width = c.Width;
                    Height = c.Height;
                }
                else
                {
                    if (ss == SameSizeEnum.Width || ss == SameSizeEnum.Both)
                        c.Width = Width;
                    if (ss == SameSizeEnum.Height || ss == SameSizeEnum.Both)
                        c.Height = Height;
                }
                i++;
            }
            s.SetSelectedComponents(selection);
        }

        private void Align(AlignEnum ss)
        {
            ISelectionService s = (ISelectionService)serviceContainer.GetService(typeof(ISelectionService));
            //ArrayList controls = s.GetSelectedComponents() as ArrayList;
            object[] selection = new object[s.SelectionCount];
            s.GetSelectedComponents().CopyTo(selection, 0);
            int i = 0;
            int X = 0;
            int Y = 0;

            foreach (Control c in selection)
            {
                if (i == 0)
                {
                    X = c.Location.X;
                    Y = c.Location.Y;
                }
                else
                {
                    if (ss == AlignEnum.Left)
                    {
                        c.Location = new Point(X, c.Location.Y);
                    }
                    if (ss == AlignEnum.Top)
                    {
                        c.Location = new Point(c.Location.X, Y);
                    }

                }
                i++;
            }
            s.SetSelectedComponents(selection);
        }

        #region Control selection methods/events

        public void SelectByEntityTypeVersionId(int i_EntityTypeVersionID)
        {
            ISelectionService s = (ISelectionService)serviceContainer.GetService(typeof(ISelectionService));
            ArrayList components = new ArrayList();
            foreach (Control c in m_form.Controls)
            {
                if (c.Name.EndsWith("_" + i_EntityTypeVersionID.ToString()))
                {
                    m_form.ScrollControlIntoView(c);
                    components.Add(c);
                }
            }
            s.SetSelectedComponents(components);
        }

        public void SelectByLineage(string Lineage)
        {
            ISelectionService s = (ISelectionService)serviceContainer.GetService(typeof(ISelectionService));
            ArrayList components = new ArrayList();
            foreach (Control c in m_form.Controls)
            {
                if (c.Name.StartsWith("lbl_"))
                {
                    c.BackColor = System.Drawing.Color.Transparent;
                }
                if (c.Name.EndsWith("_" + Lineage))
                {
                    m_form.ScrollControlIntoView(c);
                    components.Add(c);
                    if (c.Name.StartsWith("lbl_"))
                    {
                        c.BackColor = System.Drawing.Color.PowderBlue;
                    }
                }
            }
            s.SetSelectedComponents(components);
        }

        private void SelectAllComponents()
        {
            ISelectionService s = (ISelectionService)serviceContainer.GetService(typeof(ISelectionService));
            ArrayList components = new ArrayList();
            foreach (Control c in m_form.Controls)
            {
                components.Add(c);
            }
            s.SetSelectedComponents(components);
        }

        private void OnSelectionChanged(object sender, System.EventArgs e)
        {
            ISelectionService s = (ISelectionService)serviceContainer.GetService(typeof(ISelectionService));

            object[] selection;
            if (s.SelectionCount == 0)
                MainForm.m_propertyWindow.PropertyGridSelectedObject = null;
            //MainForm.m_propertyWindow.PropertyGridSelectedObject = null;
            else
            {
                selection = new object[s.SelectionCount];
                s.GetSelectedComponents().CopyTo(selection, 0);
                if (s.SelectionCount == 1)
                {
                    MainForm.m_propertyWindow.PropertyGridSelectedObject = selection[0];
                    string[] hiddenProperties = new string[] { "Name" };
                    MainForm.m_propertyWindow.propertyGrid.HiddenProperties = hiddenProperties;
                }
                else
                {
                    MainForm.m_propertyWindow.PropertyGridSelectedObjects = selection;
                }
            }

            if (s.PrimarySelection == null)
            {
                //lblSelectedComponent.Text = "";
            }
            else
            {
                IComponent component = (IComponent)s.PrimarySelection;
                //lblSelectedComponent.Text = component.Site.Name + " (" + component.GetType().Name + ")";
            }
        }

        #endregion

        private void pnlDragHere_DragDrop(object sender, DragEventArgs e)
        {
            CXMLTreeNode data = (CXMLTreeNode)e.Data.GetData(typeof(CXMLTreeNode));
            if (data != null)
            {
                if (data.Level == 0)
                {
                    m_form.Text = data.Text;
                    this.Text = "Form Designer - " + data.Text;
                    if (data.BusinessEntity != null)
                    {
                        RootBusinessEntity = data.BusinessEntity;
                        if (data.EntityType != null)
                        {
                            this.EntityType = data.EntityType;
                        }
                        lbl_EntityName.Text = data.BusinessEntity.Name;
                        lbl_ContextTxt.Text = data.BusinessEntity.EntityType.EntityTypeContextName;
                        lbl_EntityVersionTxt.Text = data.BusinessEntity.EntityVersion.FullVersion;
                        if (data.BusinessEntity.ParentProject != null)
                        {
                            Project p = data.BusinessEntity.ParentProject;
                            groupBox1.Text = "Project: " + p.Name;
                            lbl_ProjectScopeTxt.Text = p.Scope.Name;
                            lbl_ProjectContextTxt.Text = p.Context.Name;
                            OnEntityDroppedInFormDesigner(this);
                        }
                        //BehaviorService bs = (BehaviorService)serviceContainer.GetService(typeof(BehaviorService));
                        //bs.PushCaptureBehavior(new MyBehavior(m_form));
                    }
                }
                ((MainForm)m_parent).SetStatus("Generating Form ...");
                ((MainForm)m_parent).Update();

                try
                {
                    SetDoubleBuffered(m_form);
                    SetDoubleBuffered(this);
                    progressBar1.Value = 0;
                    //Traverse all node structure and set node Top/Left positions
                    //to then generate Controls and add them to the Form
                    NodeToControls(data);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(this, "Excelption:" + ex.Message, "CXMLStudio", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }

        public static void SetDoubleBuffered(System.Windows.Forms.Control c)
        {
            //Taxes: Remote Desktop Connection and painting
            //http://blogs.msdn.com/oldnewthing/archive/2006/01/03/508694.aspx
            if (System.Windows.Forms.SystemInformation.TerminalServerSession)
                return;

            System.Reflection.PropertyInfo aProp =
                  typeof(System.Windows.Forms.Control).GetProperty(
                        "DoubleBuffered",
                        System.Reflection.BindingFlags.NonPublic |
                        System.Reflection.BindingFlags.Instance);

            aProp.SetValue(c, true, null);
        }

        private void StartAddControlsToFormWorker(ArrayList Nodes)
        {
            backgroundWorker1.RunWorkerAsync(Nodes);
        }

        private void NodeToControls(CXMLTreeNode node)
        {
            ArrayList Nodes = PrepareNodesForForm(node);
            StartAddControlsToFormWorker(Nodes);
        }

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {

            ArrayList Nodes = e.Argument as ArrayList;
            AddControlsDelegate acd = new AddControlsDelegate(CreateDummyControl);
            if (Nodes.Count > 20)
            {
                InitProgressBarDelegate ipbd = new InitProgressBarDelegate(InitProgressBar);
                this.Invoke(ipbd, Nodes.Count);
            }
            SuspendLayoutDelegate sld = new SuspendLayoutDelegate(MySuspendLayout);
            this.Invoke(sld);
            PerformStepDelegate psd = new PerformStepDelegate(PerformStep);

            using (DesignerTransaction t = host.CreateTransaction("Creating Controls"))
            {
                foreach (CXMLTreeNode node in Nodes)
                {
                    using (node)
                    {
                        this.Invoke(acd, node);
                        this.Invoke(psd);
                    }
                }
            }

            ResumeLayoutDelegate rld = new ResumeLayoutDelegate(MyResumeLayout);
            this.Invoke(rld, Nodes.Count);
        }

        #region Worker events definition
        private void InitProgressBar(int count)
        {
            //Initialize Progress Bar
            progressBar1.Maximum = count;
            progressBar1.Step = 1;
            lblProgress.Text = "Building Form Please Wait...";
            pnl_Progress.Visible = true;
            pnl_Progress.Refresh();
        }
        private void MySuspendLayout()
        {
            m_form.SuspendLayout();
            DrawingControl.SuspendDrawing(m_form);
        }
        private void MyResumeLayout(int nodecount)
        {
            lblProgress.Text = lblProgress.Text + "...Done!";
            ((MainForm)m_parent).SetStatus("Done!");
            pnl_Progress.Update();

            DrawingControl.ResumeDrawing(m_form);
            m_form.ResumeLayout(true);
            if (nodecount > 20)
            {
                Thread.Sleep(700);
                pnl_Progress.Visible = false;
                //pnlViewHost.Height = m_form.Height;
            }
            isFormCompleted = true;
            OnFormCompleted(this);
        }
        private void PerformStep()
        {
            progressBar1.PerformStep();
        }
        #endregion

        private void CreateDummyControl(CXMLTreeNode node)
        {
            Label lbl = null;
            Control txt = null;
            object tmpcontrol = null;
            string sZ_ControlName = "";
            string sZ_LabelName = "";
            bool isDuplicate = false;

            try
            {
                ((Form)host.RootComponent).SuspendLayout();
                if (node.BusinessEntity != null)
                {
                    tmpcontrol = m_propsbl.GetControlFromBinary(node.BusinessEntity.EntityTypeVersions.EntityTypeVersionsID, node.Lineage, DisplayContext.FormDesigner, ControlType.Control);
                    if (tmpcontrol != null)
                    {
                        byte[] bytes = m_propsdal.GetBinaryControl(node.BusinessEntity.EntityTypeVersions.EntityTypeVersionsID, node.Lineage, Convert.ToInt32(DisplayContext.FormDesigner), Convert.ToInt32(ControlType.Control));
                        if (bytes != null && !((CXMLStudioIDE.DesignerHost.DesignerHost)host).ContainsName(((Control)tmpcontrol).Name))
                        {
                            txt = ControlFactory.DeserializeControlFromBin(bytes, host, tmpcontrol.GetType(), ((Control)tmpcontrol).Name) as Control;
                            if (txt != null)
                            {
                                sZ_ControlName = txt.Name;
                            }
                        }
                        else
                        {
                            isDuplicate = true;
                        }
                    }
                }

                if (node.BusinessEntity != null && (node.Lineage != null))
                {
                    sZ_LabelName = "lbl_" + node.Lineage;
                    //Check if Control name exists. If not then assign a name
                    if (!((CXMLStudioIDE.DesignerHost.DesignerHost)host).ContainsName(sZ_LabelName))
                    {
                        lbl = (Label)host.CreateComponent(typeof(Label), sZ_LabelName);
                    }
                }
                //Create control with auto-generated Name.
                if (lbl == null)
                {
                    //Debug.WriteLine(node.Name + "," + node.Lineage);
                    lbl = (Label)host.CreateComponent(typeof(Label));
                }
                PropertyDescriptor lbl_Text = TypeDescriptor.GetProperties(lbl)["Text"];
                PropertyDescriptor lbl_Top = TypeDescriptor.GetProperties(lbl)["Top"];
                PropertyDescriptor lbl_Left = TypeDescriptor.GetProperties(lbl)["Left"];
                PropertyDescriptor lbl_Width = TypeDescriptor.GetProperties(lbl)["Width"];
                lbl_Text.SetValue(lbl, node.Text);
                lbl_Width.SetValue(lbl, 150);
                /* If No properties in DB found then set the default top/left positions */
                if (txt == null)
                {
                    lbl_Top.SetValue(lbl, node.Top);
                    lbl_Left.SetValue(lbl, node.Left);

                    if (node.BusinessEntity != null && node.Lineage != null && !isDuplicate)
                    {
                        if (!((CXMLStudioIDE.DesignerHost.DesignerHost)host).ContainsName(sZ_ControlName))
                        {
                            switch (node.PropertyType)
                            {
                                case "DateTime":
                                    sZ_ControlName = "dtp_" + node.Lineage;
                                    txt = (DateTimePicker)host.CreateComponent(typeof(DateTimePicker), sZ_ControlName);
                                    break;
                                case "Boolean":
                                    sZ_ControlName = "chk_" + node.Lineage;
                                    txt = (CheckBox)host.CreateComponent(typeof(CheckBox), sZ_ControlName);
                                    break;
                                default:
                                    sZ_ControlName = "txt_" + node.Lineage;
                                    txt = (TextBox)host.CreateComponent(typeof(TextBox), sZ_ControlName);
                                    break;
                            }
                        }
                        else
                        {
                            Debug.WriteLine("FormDesigner Error: Control already exists in Form :\n" +
                                "Ctrl Name:" + sZ_ControlName + " Node Name:" + node.Name + " path:" + node.BindingName);
                        }
                    }
                }
                /* Otherwise set the label top/left relative to the generated txt Control */
                else
                {
                    lbl_Top.SetValue(lbl, txt.Top);
                    lbl_Left.SetValue(lbl, txt.Left - 160);
                }
                lbl.Parent = (Form)host.RootComponent;

                if (node.IsAttribute)
                {
                    lbl.Font = new System.Drawing.Font("Microsoft Sans Serif", 8, FontStyle.Italic);
                }

                if (tmpcontrol == null && txt != null)
                {
                    PropertyDescriptor txt_Width = TypeDescriptor.GetProperties(txt)["Width"];
                    PropertyDescriptor txt_Left = TypeDescriptor.GetProperties(txt)["Left"];
                    PropertyDescriptor txt_Top = TypeDescriptor.GetProperties(txt)["Top"];
                    txt_Width.SetValue(txt, 200);
                    txt_Left.SetValue(txt, lbl.Left + 10 + lbl.Width);
                    txt_Top.SetValue(txt, lbl.Top);
                    txt.Parent = (Form)host.RootComponent;
                    //If properties not in database then save them
                    if (node != null && node.BusinessEntity != null && node.Lineage != null)
                    {
                        m_propsbl.SaveControlBinaryProperties(txt, node.BusinessEntity.EntityTypeVersions.EntityTypeVersionsID, node.Lineage, DisplayContext.FormDesigner, ControlType.Control);
                    }
                }
                //ccs.OnComponentChanging(m_form, null);
                //m_form.Controls.Add(lbl);
                //m_form.Controls.Add(txt);
                //ccs.OnComponentChanged(m_form, null, null, null);

                //SET THE VERBS(RIGHT-CLICK CONTEXTUAL MENU ITEMS) FOR THIS PARTICULAR CONTROL
                if (txt != null)
                {
                    IDesigner designer = host.GetDesigner(txt);
                    DesignerVerb m_Verb = new DesignerVerb("Properties", new EventHandler(OnPropertiesSelected));
                    designer.Verbs.Add(m_Verb);
                    AddConversionVerbs(txt);
                }
            }
            catch (Exception e)
            {
                MessageBox.Show(this, "Exception:\n" + e.Message + " node name:" + node.Name +
                " ctrlname:" + sZ_ControlName + " path:" + node.BindingName, "CXMLStudio", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            finally
            {
                ((Form)host.RootComponent).ResumeLayout();
            }
        }

        public void LoadControl(CXMLTreeNode node, string name)
        {
            CXMLPropertiesUtil pbl = new CXMLPropertiesUtil();
            BusinessEntity b = node.BusinessEntity;

            if (b != null)
            {
                PropertiesBL pBl = new PropertiesBL();
                PropertySet ps = pBl.GetPropertiesForEntity(MainForm.m_currentcontext, b.Name, b.EntityTypeVersions.EntityTypeVersionsID);
                Type t = ControlFactory.GetControlTypeFromName(name);
                Control c = (Control)host.CreateComponent(t, name);
                ControlFactory.SetControlProperties(c, ps);
                c.Parent = (Form)host.RootComponent;
            }
        }

        private void AddConversionVerbs(Control c)
        {
            IDesigner designer = host.GetDesigner(c);
            DesignerVerbCollection dvc = new DesignerVerbCollection();
            dvc.Add(new MyDesignerVerb("Convert to Dropdown list", new EventHandler(OnChangeControlSelected), c, typeof(ComboBox)));
            dvc.Add(new MyDesignerVerb("Convert to RadioButton", new EventHandler(OnChangeControlSelected), c, typeof(RadioButton)));
            dvc.Add(new MyDesignerVerb("Convert to TextBox", new EventHandler(OnChangeControlSelected), c, typeof(TextBox)));
            dvc.Add(new MyDesignerVerb("Convert to Label", new EventHandler(OnChangeControlSelected), c, typeof(Label)));
            dvc.Add(new MyDesignerVerb("Convert to CheckBox", new EventHandler(OnChangeControlSelected), c, typeof(CheckBox)));
            dvc.Add(new MyDesignerVerb("Convert to DateTimePicker", new EventHandler(OnChangeControlSelected), c, typeof(DateTimePicker)));
            foreach (DesignerVerb verb in dvc)
            {
                if ((c.GetType() == typeof(ComboBox) && verb.Text.Contains("Dropdown")) ||
                    (c.GetType() == typeof(TextBox) && verb.Text.Contains(c.GetType().Name)) ||
                    (c.GetType() == typeof(Label) && verb.Text.Contains(c.GetType().Name)) ||
                    (c.GetType() == typeof(RadioButton) && verb.Text.Contains(c.GetType().Name)) ||
                    (c.GetType() == typeof(CheckBox) && verb.Text.Contains(c.GetType().Name)) ||
                    (c.GetType() == typeof(DateTimePicker) && verb.Text.Contains(c.GetType().Name)))
                {
                    continue;
                }
                designer.Verbs.Add(verb);
            }

        }

        #region DummyControl Verb Events declaration

        private void OnPropertiesSelected(object sender, EventArgs args)
        {
            // Display a message
            //MessageBox.Show("Properties was invoked.");
            ISelectionService s = (ISelectionService)serviceContainer.GetService(typeof(ISelectionService));
            ICollection controls = s.GetSelectedComponents();
            foreach (Control c in controls)
            {
                //MessageBox.Show(c.Name);
            }
            MainForm.m_propertyWindow.Show();
        }

        private void OnChangeControlSelected(object sender, EventArgs args)
        {
            MyDesignerVerb verb = sender as MyDesignerVerb;
            if (verb != null)
            {
                ISelectionService s = (ISelectionService)serviceContainer.GetService(typeof(ISelectionService));
                ICollection controls = s.GetSelectedComponents();
                foreach (Control c in controls)
                {
                    ChangeControlType(c, verb.NewType);
                }
                //Once all selected controls have been used to create new ones of new type then 
                //delete the old ones.
                menuService.GlobalInvoke(StandardCommands.Delete);
            }
        }

        #endregion

        /* On Component changed, save properties like resizing */
        private void FormDesigner_ComponentChanged(object sender, ComponentChangedEventArgs e)
        {
            Control c = e.Component as Control;
            if (c != null && isFormCompleted)
            {
                if (c.Name.StartsWith("txt_") || c.Name.StartsWith("lbl_") ||
                    c.Name.StartsWith("rb_") || c.Name.StartsWith("chk_") ||
                    c.Name.StartsWith("cmb_") || c.Name.StartsWith("dtp_"))
                {
                    string lineage = CXMLStudioIDE.Common.Common.GetLineageFromControlName(c.Name);
                    int etvid = CXMLStudioIDE.Common.Common.GetEntityTypeVersionIDFromControlName(c.Name);
                    if (lineage != null && etvid > 0)
                    {
                        m_propsbl.SaveControlBinaryProperties(c, etvid, lineage, DisplayContext.FormDesigner, ControlType.Control);
                    }
                }
            }
        }

        private void ChangeControlType(Control oldc, Type newtype)
        {
            string sZ_ControlName = "";
            string name_preffix = "";
            Control newcontrol = null;

            name_preffix = ControlFactory.GetPrefixFromControlTypeName(newtype.Name);

            if (oldc.GetType() != newtype)
            {
                using (DesignerTransaction t = ((CXMLStudioIDE.DesignerHost.DesignerHost)host).CreateTransaction("Changing control type"))
                {
                    if (oldc.Name.StartsWith("txt_") || oldc.Name.StartsWith("lbl_") ||
                        oldc.Name.StartsWith("cmb_") || oldc.Name.StartsWith("rb_") ||
                        oldc.Name.StartsWith("chk_") || oldc.Name.StartsWith("dtp_"))
                    {
                        sZ_ControlName = name_preffix + oldc.Name.Substring(oldc.Name.IndexOf("_") + 1);
                    }

                    if (!((CXMLStudioIDE.DesignerHost.DesignerHost)host).ContainsName(sZ_ControlName))
                    {
                        newcontrol = host.CreateComponent(newtype, sZ_ControlName) as Control;
                    }
                    if (newcontrol == null)
                    {
                        newcontrol = host.CreateComponent(newtype) as Control;
                    }

                    //PropertyDescriptor Text = TypeDescriptor.GetProperties(oldc)["Text"];
                    //Text.SetValue(newcontrol, oldc.Text);
                    PropertyDescriptor Top = TypeDescriptor.GetProperties(oldc)["Top"];
                    PropertyDescriptor Left = TypeDescriptor.GetProperties(oldc)["Left"];
                    PropertyDescriptor Width = TypeDescriptor.GetProperties(oldc)["Width"];
                    Top.SetValue(newcontrol, oldc.Top);
                    Left.SetValue(newcontrol, oldc.Left);
                    Width.SetValue(newcontrol, oldc.Width);
                    newcontrol.Parent = (Form)host.RootComponent;

                    //If properties not in database then save them
                    string lineage = CXMLStudioIDE.Common.Common.GetLineageFromControlName(sZ_ControlName);
                    int etvid = CXMLStudioIDE.Common.Common.GetEntityTypeVersionIDFromControlName(sZ_ControlName);
                    if (lineage != null && etvid > 0)
                    {
                        m_propsbl.SaveControlBinaryProperties(newcontrol, etvid, lineage, DisplayContext.FormDesigner, ControlType.Control);
                    }

                    //SET THE VERBS(RIGHT-CLICK CONTEXTUAL MENU ITEMS) FOR THIS PARTICULAR CONTROL
                    IDesigner designer = host.GetDesigner(newcontrol);
                    designer.Verbs.Add(new DesignerVerb("Properties", new EventHandler(OnPropertiesSelected)));
                    AddConversionVerbs(newcontrol);
                }
            }
        }

        private void pnlDragHere_DragEnter(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(typeof(CXMLTreeNode)))
            {
                e.Effect = DragDropEffects.Copy;
                pnlDragHere_DragDrop(sender, e);
            }
            else
            {
                e.Effect = DragDropEffects.None;
            }
        }

        private void pnlDragHere_MouseMove(object sender, MouseEventArgs e)
        {
            if (isBuildingForm)
                return;
        }

        private void lblDragHere_Click(object sender, EventArgs e)
        {

        }

        #region ToolStripMenuItem Event handling

        private void deleteToolStripMenuItem_Click(object sender, EventArgs e)
        {
            menuService.GlobalInvoke(StandardCommands.Delete);
        }

        private void selectAllToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SelectAllComponents();
        }

        private void widthToolStripMenuItem_Click(object sender, EventArgs e)
        {
            MakeSameSize(SameSizeEnum.Width);
        }

        private void heightToolStripMenuItem_Click(object sender, EventArgs e)
        {
            MakeSameSize(SameSizeEnum.Height);
        }

        private void bothToolStripMenuItem_Click(object sender, EventArgs e)
        {
            MakeSameSize(SameSizeEnum.Both);
        }

        private void leftAlignToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Align(AlignEnum.Left);
        }

        private void topAlignToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Align(AlignEnum.Top);
        }

        private void copyToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ISelectionService s = (ISelectionService)serviceContainer.GetService(typeof(ISelectionService));
            object[] selection = new object[s.SelectionCount];
            s.GetSelectedComponents().CopyTo(selection, 0);
            ControlFactory.CopyCtrls2ClipBoard(selection);
        }

        private void pasteToolStripMenuItem_Click(object sender, EventArgs e)
        {
            object[] controls = ControlFactory.GetCtrlsFromClipBoard();
            foreach (Control c in controls)
            {
                //TODO logic to build control on copy/paste 
            }
        }

        private void formPreviewToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SaveFormToXml(null, true);
        }

        private void openToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string fileName = null;
            try
            {
                // Open File Dialog
                OpenFileDialog dlg = new OpenFileDialog();
                dlg.DefaultExt = "xml";
                dlg.Filter = "Xml Files|*.xml";
                if (dlg.ShowDialog() == DialogResult.OK)
                    fileName = dlg.FileName;

                if (fileName == null)
                    return;

                //BasicHostLoader bhl = new BasicHostLoader(fileName);
                //serviceContainer = new ServiceContainer();
                //IDesignerHost newhost = new CXMLStudioIDE.DesignerHost.DesignerHost(serviceContainer);
                //((CXMLStudioIDE.DesignerHost.DesignerHost)newhost).BeginLoad(bhl);
                //this.Controls.Clear();
                //this.Controls.Add(newhost.RootComponent as Form);
                //this.Update();

                FormDesigner fd = new FormDesigner(m_parent, fileName);
                fd.Show(((MainForm)m_parent).dockPanel);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void cutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            menuService.GlobalInvoke(StandardCommands.Cut);
        }

        private void testToolStripMenuItem_Click(object sender, EventArgs e)
        {

            m_form.Invalidate();
            m_form.Update();
        }

        #endregion

        //This method sets the coordinates for the controls when
        //creating a Form from scratch. 
        private ArrayList PrepareNodesForForm(CXMLTreeNode node)
        {
            CXMLTreeNode temp = node;
            ArrayList Nodes = new ArrayList(node.GetNodeCount(true));
            int x, y;
            x = 10;
            y = 10;
            if (temp.Nodes.Count == 0)
            {

                Nodes.Add(node);
            }
            //Loop through the Parent Nodes
            for (int k = 0; k < temp.Nodes.Count; k++)
            {
                //Store the Parent Node in temp
                temp = temp.Nodes[k] as CXMLTreeNode;
                if (temp.DisplayInForm)
                    y += 30;
                node.Left = 10;
                node.Top = y;

                if (node.DisplayInForm)
                {
                    Nodes.Add(node);
                }

                //Now Loop through each of the child nodes in this parent node i.e.temp
                for (int i = 0; i < temp.Nodes.Count; i++)
                {
                    //Debug.WriteLine("Parent: " + temp.Name + "  Child:" + temp.Nodes[i].Name);
                    if (temp.DisplayInForm)
                    {
                        y += 30;
                    }
                    visitChildNodes((CXMLTreeNode)temp.Nodes[i], 40, ref y, ref Nodes); //send every child to the function for further traversal
                }
            }
            return Nodes;
        }

        private void visitChildNodes(CXMLTreeNode node, int x, ref int y, ref ArrayList Nodes)
        {
            //Create a TreeViewItem object for this children
            if (node != null)
            {
                node.Left = x;
                node.Top = y;
                if (node.DisplayInForm)
                {
                    Nodes.Add(node);

                    if (node.Nodes.Count == 0)
                    {
                        y += 30;
                    }
                }

                //Loop Through this node and its childs recursively
                for (int j = 0; j < node.Nodes.Count; j++)
                {
                    if (j == 0)
                    {
                        x += 30;
                    }
                    if (node.DisplayInForm)
                    {
                        y += 30;
                    }
                    visitChildNodes(node.Nodes[j] as CXMLTreeNode, x, ref y, ref Nodes);
                }
            }
        }

        #region IFormDesignerView Members

        public bool ControlExists(string sZ_ControlName)
        {
            foreach (Control c in m_form.Controls)
            {
                if (c.Name.Equals(sZ_ControlName))
                    return true;
            }
            return false;
        }

        public void SaveFormToXml(string fileName, bool forceFilePrompt)
        {
            try
            {
                int filterIndex = 3;

                if ((fileName == null) || forceFilePrompt)
                {
                    SaveFileDialog dlg = new SaveFileDialog();

                    dlg.DefaultExt = "xml";
                    dlg.Filter = "XML Files|*.xml";
                    if (dlg.ShowDialog() == DialogResult.OK)
                    {
                        fileName = dlg.FileName;
                        filterIndex = dlg.FilterIndex;
                    }
                }

                if (fileName != null)
                {
                    switch (filterIndex)
                    {
                        case 1:
                            FormSerializer s = new FormSerializer(host);
                            XmlDocument xml = s.PerformFlushWorker();
                            // Write out our xmlDocument to a file.
                            StringWriter sw = new StringWriter();
                            XmlTextWriter xtw = new XmlTextWriter(sw);

                            xtw.Formatting = Formatting.Indented;
                            xml.WriteTo(xtw);
                            // Get rid of our artificial super-root before we save out
                            // the XML.
                            //
                            string cleanup = sw.ToString().Replace("<DOCUMENT_ELEMENT>", "");

                            cleanup = cleanup.Replace("</DOCUMENT_ELEMENT>", "");
                            xtw.Close();

                            StreamWriter file = new StreamWriter(fileName);

                            file.Write(cleanup);
                            file.Close();
                            break;
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error during save: " + ex.ToString());
            }
        }

        public void FormDesigner_FormClosing(object sender, FormClosingEventArgs e)
        {
            /**Do we really need this?? **/
            //DialogResult result = MessageBox.Show(this, "Save current Form?", "CXMLStudioIDE", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
            //if (result == DialogResult.Yes || result == DialogResult.No)
            //{
            //    if (result == DialogResult.Yes)
            //    {
            //    }
            //    this.Dispose();
            //}
            //else
            //{
            //    e.Cancel = true;
            //}

        }

        #endregion

    }
    class DrawingControl
    {
        [DllImport("user32.dll")]
        public static extern int SendMessage(IntPtr hWnd, Int32 wMsg, bool wParam, Int32 lParam);

        private const int WM_SETREDRAW = 11;

        public static void SuspendDrawing(Control parent)
        {
            SendMessage(parent.Handle, WM_SETREDRAW, false, 0);
        }

        public static void ResumeDrawing(Control parent)
        {
            SendMessage(parent.Handle, WM_SETREDRAW, true, 0);
            parent.Refresh();
        }
    }


}
